package workers;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public abstract class TimedWorker {

	public static final String PROPERTY_DESCRIPTION = "description";
	public static final String PROPERTY_CURRENT_ACTION= "currentAction";
	public static final String PROPERTY_TASK_LENGTH = "taskLength";
	public static final String PROPERTY_TASK_PROGRESS = "taskProgress";
	public static final String PROPERTY_IS_WORKING = "isWorking";
	public static final String PROPERTY_CANCELED = "canceled";
	
	private boolean isWorking;
	private StopWatch stopWatch;
	String taskDescription;
	private long taskLength;
	private long taskProgress;
	private boolean canceled;
	private String currentAction;
	protected PropertyChangeSupport propertyChangeSupport;
	
	protected TimedWorker( String taskDescription , PropertyChangeListener changeListener ){
		propertyChangeSupport = new PropertyChangeSupport(this);
		propertyChangeSupport.addPropertyChangeListener(changeListener);
		stopWatch  = new StopWatch();
		this.taskDescription = taskDescription;
		canceled = false;
		currentAction = "constructing";
	}
	
	public StopWatch getStopWatch(){
		return stopWatch;
	}
	
	public String getTaskDescription(){
		return taskDescription;
	}
	
	protected void startWork(){
		stopWatch.start();
		isWorking = true;
		propertyChangeSupport.firePropertyChange(new PropertyChangeEvent(this, PROPERTY_IS_WORKING , Boolean.FALSE, Boolean.TRUE));
	}
	
	protected void stopWork(){
		stopWatch.stop();
		isWorking = false;
		propertyChangeSupport.firePropertyChange(new PropertyChangeEvent(this, PROPERTY_IS_WORKING, Boolean.TRUE, Boolean.FALSE));
	}
	
	public boolean isWorking(){
		return isWorking;
	}
	
	public void setTaskLength( long tl ){
		Long oldVal = new Long( tl ) ;
		Long newVal = new Long( tl );
		taskLength = tl;
		propertyChangeSupport.firePropertyChange(new PropertyChangeEvent(this, PROPERTY_TASK_LENGTH, oldVal, newVal));
	}
	
	public long getTaskLength(){
		return taskLength;
	}
	
	public void setTaskProgress( long l ){
		Long oldVal = new Long( taskProgress );
		Long newVal = new Long( l );
		taskProgress = l;
		propertyChangeSupport.firePropertyChange(new PropertyChangeEvent( this, PROPERTY_TASK_PROGRESS , oldVal, newVal ) );
	}
	
	public long getTaskProgress(){
		return taskProgress;
	}
		
	@Override
	public String toString() {
	
		int percent =  (taskLength!=0)? (int)(100 * taskProgress / taskLength):0;
		String progress = "[ " + percent + "% ]";
		String time = "[ " + stopWatch.getElapsedTime() + "ms ]";
		String action = "(" + currentAction + ")";
		if(canceled) return taskDescription + "  [ Canceled ] " + action; 
		if(isWorking) return taskDescription + "  " + progress + " " + action;
		else return taskDescription + "  " + time + " " + action;
	}			
	public PropertyChangeSupport getChangeSupport(){
		return propertyChangeSupport;
	}
	
	public abstract void cancelTask();
	
	public void setCanceled( boolean b ){
		canceled = b;
		propertyChangeSupport.firePropertyChange(new PropertyChangeEvent( this, PROPERTY_CANCELED , Boolean.valueOf(!b), Boolean.valueOf(b) ) );
	}

	public boolean isCanceled(){
		return canceled;
	}
	
	public void setCurrentAction( String act ){
		String old = currentAction;
		currentAction = act;
		propertyChangeSupport.firePropertyChange(new PropertyChangeEvent( this, PROPERTY_CURRENT_ACTION , old,   currentAction ) );
	}
	
}
